"""
价值投资分析引擎
基于PRD精简版的评分体系和分析算法
"""

import pandas as pd
import numpy as np
from typing import Dict, Any, List, Tuple
from datetime import datetime
import logging

from config import (
    SCORING_WEIGHTS, ASSET_QUALITY_WEIGHTS, 
    FINANCIAL_SAFETY_WEIGHTS, GROWTH_POTENTIAL_WEIGHTS, SCORE_GRADES
)
from account_mapping import account_classifier
from database import db_manager

logger = logging.getLogger(__name__)


class ValueInvestmentAnalyzer:
    """价值投资分析器"""
    
    def __init__(self):
        """初始化分析器"""
        self.scoring_weights = SCORING_WEIGHTS
        self.asset_quality_weights = ASSET_QUALITY_WEIGHTS
        self.financial_safety_weights = FINANCIAL_SAFETY_WEIGHTS
        self.growth_potential_weights = GROWTH_POTENTIAL_WEIGHTS
        self.score_grades = SCORE_GRADES
    
    def analyze_stock(self, stock_code: str, data: pd.DataFrame) -> Dict[str, Any]:
        """
        对股票进行完整的价值投资分析
        
        Args:
            stock_code: 股票代码
            data: 资产负债表数据
            
        Returns:
            包含所有分析结果的字典
        """
        if data.empty:
            logger.error(f"股票 {stock_code} 数据为空")
            return {}
        
        try:
            # 数据预处理
            processed_data = self._preprocess_data(data)
            
            # 计算基础财务指标
            basic_metrics = self._calculate_basic_metrics(processed_data)
            
            # 资产质量评分
            asset_quality_score = self._calculate_asset_quality_score(processed_data, basic_metrics)
            
            # 财务安全评分
            financial_safety_score = self._calculate_financial_safety_score(processed_data, basic_metrics)
            
            # 成长潜力评分
            growth_potential_score = self._calculate_growth_potential_score(processed_data, basic_metrics)
            
            # 综合评分
            total_score = self._calculate_total_score(
                asset_quality_score, financial_safety_score, growth_potential_score
            )
            
            # 评分等级
            grade = self._get_score_grade(total_score)
            
            # 风险预警
            risk_warnings = self._generate_risk_warnings(processed_data, basic_metrics)
            
            # 投资建议
            investment_advice = self._generate_investment_advice(
                total_score, grade, risk_warnings
            )
            
            analysis_result = {
                'stock_code': stock_code,
                'analysis_date': datetime.now().isoformat(),
                'basic_metrics': basic_metrics,
                'scores': {
                    'asset_quality': asset_quality_score,
                    'financial_safety': financial_safety_score,
                    'growth_potential': growth_potential_score,
                    'total_score': total_score,
                    'grade': grade
                },
                'risk_warnings': risk_warnings,
                'investment_advice': investment_advice,
                'data_summary': {
                    'periods_count': len(processed_data),
                    'latest_period': str(processed_data['报告日期'].max()),
                    'earliest_period': str(processed_data['报告日期'].min())
                }
            }
            
            # 保存分析结果到缓存
            db_manager.save_analysis_result(
                stock_code, 'value_investment_analysis', analysis_result
            )
            
            return analysis_result
            
        except Exception as e:
            logger.error(f"分析股票 {stock_code} 时发生错误: {e}")
            return {}
    
    def _preprocess_data(self, data: pd.DataFrame) -> pd.DataFrame:
        """数据预处理"""
        # 按日期和分类聚合数据
        aggregated = account_classifier.aggregate_by_category(data)
        
        # 透视表格式，便于计算
        pivot_data = aggregated.pivot_table(
            index='报告日期',
            columns='category',
            values='金额',
            fill_value=0
        ).reset_index()
        
        # 按日期排序
        pivot_data = pivot_data.sort_values('报告日期')
        
        return pivot_data
    
    def _calculate_basic_metrics(self, data: pd.DataFrame) -> Dict[str, Any]:
        """计算基础财务指标"""
        if data.empty:
            return {}
        
        latest_data = data.iloc[-1]  # 最新一期数据
        
        # 计算各大类总额
        current_assets = self._sum_categories(latest_data, ['cash_equivalents', 'receivables', 'prepayments', 'inventory', 'other_current_assets'])
        non_current_assets = self._sum_categories(latest_data, ['long_term_investments', 'fixed_assets', 'intangible_goodwill', 'other_non_current_assets'])
        total_assets = current_assets + non_current_assets
        
        current_liabilities = self._sum_categories(latest_data, ['short_term_debt', 'payables', 'advance_receipts', 'accrued_expenses', 'other_current_liabilities'])
        non_current_liabilities = self._sum_categories(latest_data, ['long_term_debt', 'other_non_current_liabilities'])
        total_liabilities = current_liabilities + non_current_liabilities
        
        total_equity = self._sum_categories(latest_data, ['share_capital', 'capital_reserves', 'retained_earnings', 'other_equity'])
        
        # 计算关键指标
        report_date = latest_data['报告日期']
        if isinstance(report_date, str):
            report_date_str = report_date
        else:
            report_date_str = report_date.strftime('%Y-%m-%d')

        metrics = {
            'report_date': report_date_str,
            'total_assets': total_assets,
            'current_assets': current_assets,
            'non_current_assets': non_current_assets,
            'total_liabilities': total_liabilities,
            'current_liabilities': current_liabilities,
            'non_current_liabilities': non_current_liabilities,
            'total_equity': total_equity,
            
            # 资产质量指标
            'cash_ratio': self._safe_divide(latest_data.get('cash_equivalents', 0), total_assets),
            'receivables_ratio': self._safe_divide(latest_data.get('receivables', 0), total_assets),
            'inventory_ratio': self._safe_divide(latest_data.get('inventory', 0), total_assets),
            'goodwill_ratio': self._safe_divide(latest_data.get('intangible_goodwill', 0), total_equity),
            
            # 财务安全指标
            'debt_ratio': self._safe_divide(total_liabilities, total_assets),
            'current_ratio': self._safe_divide(current_assets, current_liabilities),
            'quick_ratio': self._safe_divide(current_assets - latest_data.get('inventory', 0), current_liabilities),
            'interest_debt_ratio': self._safe_divide(
                latest_data.get('short_term_debt', 0) + latest_data.get('long_term_debt', 0), 
                total_assets
            ),
        }
        
        # 计算成长性指标（需要多期数据）
        if len(data) >= 2:
            growth_metrics = self._calculate_growth_metrics(data)
            metrics.update(growth_metrics)
        
        return metrics
    
    def _sum_categories(self, data_row, categories: List[str]) -> float:
        """计算指定分类的总和"""
        total = 0
        for category in categories:
            total += data_row.get(category, 0)
        return total
    
    def _safe_divide(self, numerator: float, denominator: float) -> float:
        """安全除法，避免除零错误"""
        if denominator == 0:
            return 0
        return numerator / denominator
    
    def _calculate_growth_metrics(self, data: pd.DataFrame) -> Dict[str, float]:
        """计算成长性指标"""
        if len(data) < 2:
            return {}
        
        latest = data.iloc[-1]
        previous = data.iloc[-2]
        
        # 计算各期总资产和净资产
        latest_total_assets = self._sum_categories(latest, ['cash_equivalents', 'receivables', 'prepayments', 'inventory', 'other_current_assets', 'long_term_investments', 'fixed_assets', 'intangible_goodwill', 'other_non_current_assets'])
        previous_total_assets = self._sum_categories(previous, ['cash_equivalents', 'receivables', 'prepayments', 'inventory', 'other_current_assets', 'long_term_investments', 'fixed_assets', 'intangible_goodwill', 'other_non_current_assets'])
        
        latest_equity = self._sum_categories(latest, ['share_capital', 'capital_reserves', 'retained_earnings', 'other_equity'])
        previous_equity = self._sum_categories(previous, ['share_capital', 'capital_reserves', 'retained_earnings', 'other_equity'])
        
        latest_fixed_assets = self._sum_categories(latest, ['fixed_assets'])
        previous_fixed_assets = self._sum_categories(previous, ['fixed_assets'])
        
        return {
            'total_asset_growth': self._calculate_growth_rate(previous_total_assets, latest_total_assets),
            'equity_growth': self._calculate_growth_rate(previous_equity, latest_equity),
            'fixed_asset_growth': self._calculate_growth_rate(previous_fixed_assets, latest_fixed_assets),
        }
    
    def _calculate_growth_rate(self, previous: float, current: float) -> float:
        """计算增长率"""
        if previous == 0:
            return 0
        return (current - previous) / previous
    
    def _calculate_asset_quality_score(self, data: pd.DataFrame, metrics: Dict[str, Any]) -> Dict[str, Any]:
        """计算资产质量评分"""
        # 现金比例评分 (0-100)
        cash_score = min(100, metrics.get('cash_ratio', 0) * 100 * 4)  # 25%现金比例得满分
        
        # 应收账款占比评分 (越低越好)
        receivables_score = max(0, 100 - metrics.get('receivables_ratio', 0) * 100 * 5)  # 20%以上开始扣分
        
        # 存货效率评分 (暂时简化处理)
        inventory_score = max(0, 100 - metrics.get('inventory_ratio', 0) * 100 * 3)  # 33%以上开始扣分
        
        # 商誉风险评分 (越低越好)
        goodwill_score = max(0, 100 - metrics.get('goodwill_ratio', 0) * 100 * 2)  # 50%以上开始扣分
        
        # 加权计算
        weighted_score = (
            cash_score * self.asset_quality_weights['cash_ratio'] +
            receivables_score * self.asset_quality_weights['receivables_ratio'] +
            inventory_score * self.asset_quality_weights['inventory_efficiency'] +
            goodwill_score * self.asset_quality_weights['goodwill_risk']
        )
        
        return {
            'total_score': round(weighted_score, 2),
            'components': {
                'cash_score': round(cash_score, 2),
                'receivables_score': round(receivables_score, 2),
                'inventory_score': round(inventory_score, 2),
                'goodwill_score': round(goodwill_score, 2)
            }
        }
    
    def _calculate_financial_safety_score(self, data: pd.DataFrame, metrics: Dict[str, Any]) -> Dict[str, Any]:
        """计算财务安全评分"""
        # 资产负债率评分 (越低越好)
        debt_score = max(0, 100 - metrics.get('debt_ratio', 0) * 100 * 2)  # 50%以上开始扣分
        
        # 流动比率评分
        current_ratio = metrics.get('current_ratio', 0)
        if current_ratio >= 2:
            current_score = 100
        elif current_ratio >= 1:
            current_score = 50 + (current_ratio - 1) * 50
        else:
            current_score = current_ratio * 50
        
        # 速动比率评分
        quick_ratio = metrics.get('quick_ratio', 0)
        if quick_ratio >= 1.5:
            quick_score = 100
        elif quick_ratio >= 1:
            quick_score = 70 + (quick_ratio - 1) * 60
        else:
            quick_score = quick_ratio * 70
        
        # 有息负债占比评分 (越低越好)
        interest_debt_score = max(0, 100 - metrics.get('interest_debt_ratio', 0) * 100 * 3)  # 33%以上开始扣分
        
        # 加权计算
        weighted_score = (
            debt_score * self.financial_safety_weights['debt_ratio'] +
            current_score * self.financial_safety_weights['current_ratio'] +
            quick_score * self.financial_safety_weights['quick_ratio'] +
            interest_debt_score * self.financial_safety_weights['interest_debt_ratio']
        )
        
        return {
            'total_score': round(weighted_score, 2),
            'components': {
                'debt_score': round(debt_score, 2),
                'current_score': round(current_score, 2),
                'quick_score': round(quick_score, 2),
                'interest_debt_score': round(interest_debt_score, 2)
            }
        }
    
    def _calculate_growth_potential_score(self, data: pd.DataFrame, metrics: Dict[str, Any]) -> Dict[str, Any]:
        """计算成长潜力评分"""
        # 总资产增长率评分
        asset_growth = metrics.get('total_asset_growth', 0)
        asset_growth_score = min(100, max(0, 50 + asset_growth * 100))  # 基准50分，增长加分
        
        # 净资产增长率评分
        equity_growth = metrics.get('equity_growth', 0)
        equity_growth_score = min(100, max(0, 50 + equity_growth * 100))
        
        # 固定资产投资强度评分
        fixed_growth = metrics.get('fixed_asset_growth', 0)
        fixed_growth_score = min(100, max(0, 50 + fixed_growth * 50))  # 权重较低
        
        # 加权计算
        weighted_score = (
            asset_growth_score * self.growth_potential_weights['total_asset_growth'] +
            equity_growth_score * self.growth_potential_weights['equity_growth'] +
            fixed_growth_score * self.growth_potential_weights['fixed_asset_investment']
        )
        
        return {
            'total_score': round(weighted_score, 2),
            'components': {
                'asset_growth_score': round(asset_growth_score, 2),
                'equity_growth_score': round(equity_growth_score, 2),
                'fixed_growth_score': round(fixed_growth_score, 2)
            }
        }
    
    def _calculate_total_score(self, asset_quality: Dict, financial_safety: Dict, growth_potential: Dict) -> float:
        """计算综合评分"""
        total = (
            asset_quality['total_score'] * self.scoring_weights['asset_quality'] +
            financial_safety['total_score'] * self.scoring_weights['financial_safety'] +
            growth_potential['total_score'] * self.scoring_weights['growth_potential']
        )
        return round(total, 2)
    
    def _get_score_grade(self, score: float) -> Dict[str, str]:
        """获取评分等级"""
        for grade, range_info in self.score_grades.items():
            if range_info['min'] <= score <= range_info['max']:
                return {
                    'grade': grade,
                    'description': range_info['description']
                }
        return {'grade': 'D', 'description': '强烈不推荐'}
    
    def _generate_risk_warnings(self, data: pd.DataFrame, metrics: Dict[str, Any]) -> List[str]:
        """生成风险预警"""
        warnings = []
        
        # 高负债风险
        if metrics.get('debt_ratio', 0) > 0.7:
            warnings.append("高负债风险：资产负债率超过70%")
        
        # 流动性风险
        if metrics.get('current_ratio', 0) < 1:
            warnings.append("流动性风险：流动比率小于1")
        
        # 应收账款风险
        if metrics.get('receivables_ratio', 0) > 0.3:
            warnings.append("应收账款风险：应收账款占总资产比例超过30%")
        
        # 商誉风险
        if metrics.get('goodwill_ratio', 0) > 0.5:
            warnings.append("商誉风险：商誉占净资产比例超过50%")
        
        # 成长性风险
        if metrics.get('total_asset_growth', 0) < -0.1:
            warnings.append("成长性风险：总资产出现负增长")
        
        return warnings
    
    def _generate_investment_advice(self, total_score: float, grade: Dict, warnings: List[str]) -> str:
        """生成投资建议"""
        advice_parts = []
        
        # 基于评分的建议
        if total_score >= 90:
            advice_parts.append("该股票财务状况优秀，具有很强的投资价值。")
        elif total_score >= 80:
            advice_parts.append("该股票财务状况良好，值得考虑投资。")
        elif total_score >= 70:
            advice_parts.append("该股票财务状况一般，需要谨慎评估。")
        elif total_score >= 60:
            advice_parts.append("该股票财务状况存在一些问题，建议观望。")
        else:
            advice_parts.append("该股票财务状况较差，不建议投资。")
        
        # 基于风险预警的建议
        if warnings:
            advice_parts.append(f"需要特别关注以下风险：{'; '.join(warnings[:3])}")
        
        # 基于价值投资理念的建议
        advice_parts.append("建议结合公司基本面、行业前景和估值水平进行综合判断。")
        
        return " ".join(advice_parts)


# 全局分析器实例
value_analyzer = ValueInvestmentAnalyzer()
